#ifndef SD_PTPUBLISHER_HH_
#define SD_PTPUBLISHER_HH_

#include <fastdds/dds/domain/DomainParticipant.hpp>
#include <fastdds/dds/domain/DomainParticipantFactory.hpp>
#include <fastdds/dds/topic/TypeSupport.hpp>
#include <fastdds/dds/publisher/Publisher.hpp>

#include "SDPltDataWriterListener.hpp"

using namespace eprosima::fastdds::dds;


template <class TS_T, class DT_T>
class SDPltPublisher{

private:
    DomainParticipant* participant_;
    Publisher* pub_;
    TypeSupport typeSupport_;
    Topic* topic_;
    SDPltDataWriterListener listener_;
    DataWriter* writer_;
    std::string topicname_;
    std::string dataname_;
    bool ok_;

public:

   SDPltPublisher(std::string topicname,std::string dataname,ReliabilityQosPolicyKind reliability_):typeSupport_(new TS_T()){
        if(topicname.length()<1){
            this->ok_=false;
            return;
        }
        this->participant_=nullptr;
        this->pub_=nullptr;
        this->topic_ = nullptr;
        this->writer_=nullptr;   
        this->topicname_=topicname;
        this->dataname_=dataname;
        this->ok_=init(reliability_);
    }

    ~SDPltPublisher(){
       release();
    }

private:
    void release(){
        if(this->topic_!=nullptr){
            this->participant_->delete_topic(this->topic_); 
            this->topic_=nullptr;
        }  
        if(this->writer_!=nullptr){
            this->pub_->delete_datawriter(this->writer_);
            this->writer_=nullptr;
        }
        if(this->pub_!=nullptr){
            this->participant_->delete_publisher(this->pub_);
            this->pub_=nullptr;   
        } 
        if(this->participant_!=nullptr){
            DomainParticipantFactory::get_instance()->delete_participant(this->participant_); 
            this->participant_=nullptr;
        }
    }

    bool init(ReliabilityQosPolicyKind reliability_){
        DomainParticipantQos participantQos;
        
        participantQos.name("SD_BASE_SEQ_MESSAGE_QOS_PUB");
        this->participant_=DomainParticipantFactory::get_instance()->create_participant(0,participantQos);
        if(this->participant_==nullptr){
            std::cout<<"Domain Participant creating error!"<<std::endl;
            return false;
        }

        this->typeSupport_.register_type(this->participant_);
        this->topic_ = this->participant_->create_topic(this->topicname_,this->dataname_,TOPIC_QOS_DEFAULT);
        if(this->topic_==nullptr){
            std::cout<<"Topic creating error!"<<std::endl;      
            return false;
        }


        PublisherQos publisherqos_ = PUBLISHER_QOS_DEFAULT;
        
        this->pub_ = this->participant_->create_publisher(publisherqos_,nullptr);
        if(this->pub_ ==nullptr){
            std::cout<<"Publisher creating error!"<<std::endl;             
            return false;
        }


        DataWriterQos datawriterQos_= DATAWRITER_QOS_DEFAULT;
        ReliabilityQosPolicy reliabilityQosPolicy_;
        reliabilityQosPolicy_.kind = reliability_;
        //datawriterQos_.reliability(reliabilityQosPolicy_);

        this->writer_ = this->pub_->create_datawriter(this->topic_,datawriterQos_,&this->listener_);
        

        if(this->writer_==nullptr){
            std::cout<<"Publisher creating error!"<<std::endl;       
            return false;
        }

        return true;
    }

public:
    bool publish(DT_T& msg){          
        if(this->listener_.matched_>0)this->writer_->write(&msg);          
    }
   
};

#endif

